package com.kmust.dream.wanderingdream.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kmust.dream.wanderingdream.comm.dto.Result;
import com.kmust.dream.wanderingdream.comm.pojo.ResultBean;
import com.kmust.dream.wanderingdream.comm.pojo.ReturnMessage;
import com.kmust.dream.wanderingdream.order.config.DelayQueueConfig;
import com.kmust.dream.wanderingdream.order.dto.OrderStatus;
import com.kmust.dream.wanderingdream.order.entity.Order;
import com.kmust.dream.wanderingdream.order.entity.OrderPre;
import com.kmust.dream.wanderingdream.order.exception.DataError;
import com.kmust.dream.wanderingdream.order.service.OrderService;
import com.kmust.dream.wanderingdream.order.mapper.OrderMapper;
import com.kmust.dream.wanderingdream.order.vo.OrderVo;
import com.kmust.dream.wanderingdream.product.config.RedisConfig;
import com.kmust.dream.wanderingdream.product.entity.ProductSku;
import com.kmust.dream.wanderingdream.product.service.ProductService;
import com.kmust.dream.wanderingdream.product.service.ProductSkuService;
import com.kmust.dream.wanderingdream.product.utils.ReturnUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *
 */
@Slf4j
@Service
@Transactional
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order>
        implements OrderService {

    @Autowired(required = false)
    OrderMapper orderMapper;
    @Autowired
    ProductSkuService productSkuService;
    @Autowired
    ProductService productService;
    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * 创建订单
     *
     * @param orderPre 订单预处理类
     * @return 返回返回类
     */
    @Override
    @Transactional
    public ResultBean createOrder(OrderPre orderPre) {
        ProductSku oldSku = orderPre.getProductSku();
        try {

            ProductSku newSku = productSkuService.getOne(new QueryWrapper<ProductSku>()
                    .eq("product_id", oldSku.getProductId())
                    .eq("product_sku_properties", oldSku.getProductSkuProperties()));
            //老version
            Integer oldVersion = oldSku.getVersion();
            //新version
            Integer newVersion = newSku.getVersion();
            if (!oldVersion.equals(newVersion))
                throw new DataError("version数据不一致");
            if (orderPre.getNumber() > newSku.getProductSkuStock())
                return Result.resultBean(ReturnMessage.INSERT_FAIL.getCode(), ReturnMessage.INSERT_FAIL.getMessage(), "订单预处理数量大于剩余库存量");
            Order order = new Order().setProductSkuId(newSku.getProductSkuId()).setUsername(orderPre.getUsername()).setOrderNumber(orderPre.getNumber()).setOrderAmount(newSku.getProductSkuPrice() * orderPre.getNumber());
            int insert = orderMapper.insert(order);
            if (insert == 1) {
                //需要添加rabbitmq进行计时任务，若时间到进行查询订单状态，若未支付，重新返回。
                ResultBean resultBean = productSkuService.updateVersionAndStock(newSku, order.getOrderNumber());
                if (((boolean) resultBean.getPayload())) {
                    this.sendDelayMessage(order.getOrderId(), 15*60*1000);
                    return Result.resultBean(ReturnMessage.UPDATE_SUCCESS.getCode(), ReturnMessage.UPDATE_SUCCESS.getMessage(), order.getOrderId());
                } else
                    return Result.resultBean(ReturnMessage.UPDATE_FAIL.getCode(), ReturnMessage.UPDATE_FAIL.getMessage(), null);
            }
        } catch (DataError e) {
            return Result.resultBean(ReturnMessage.DATA_ERROR.getCode(), ReturnMessage.DATA_ERROR.getMessage(), "version数据不一致");
        } catch (Exception e) {
            return Result.resultBean(ReturnMessage.GET_FAIL.getCode(), ReturnMessage.GET_FAIL.getMessage(), "获取version失败");
        }

        return Result.resultBean(ReturnMessage.UPDATE_FAIL.getCode(), ReturnMessage.UPDATE_FAIL.getMessage(), "更新失败");
    }

    /**
     * 更新订单
     *
     * @param order 订单
     * @return resultBean
     */
    @Override
    @Transactional
    @CacheEvict(value = "order", key = "'order'+#order.orderId")
    public ResultBean updateOrder(Order order) {
        if (order.getOrderId() == null)
            return Result.resultBean(ReturnMessage.UPDATE_FAIL.getCode(), ReturnMessage.DELETE_FAIL.getMessage(), "更新的订单id是空的");
        int rows = orderMapper.updateById(order);
        if (rows == 0)
            return Result.resultBean(ReturnMessage.UPDATE_FAIL.getCode(), ReturnMessage.UPDATE_FAIL.getMessage(), "数据库更新错误");
        return Result.resultBean(ReturnMessage.UPDATE_SUCCESS.getCode(), ReturnMessage.UPDATE_SUCCESS.getMessage(), "受影响的行" + rows);
    }

    /**
     * 假删除订单
     *
     * @param orderId 订单id
     * @return 返回resultBean
     */
    @Override
    @Transactional
    @CacheEvict(value = "order", key = "'order'+#orderId")
    public ResultBean deleteOrderByOrderId(Integer orderId) {
        if (orderId < 0)
            return Result.resultBean(ReturnMessage.DELETE_FAIL.getCode(), ReturnMessage.DELETE_FAIL.getMessage(), "orderId不合法");
        try {
            orderMapper.deleteOrderByOrderId(orderId);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.resultBean(ReturnMessage.DELETE_FAIL.getCode(), ReturnMessage.DELETE_FAIL.getMessage(), "删除出现异常,异常是" + e.getMessage());
        }
        return Result.resultBean(ReturnMessage.DELETE_SUCCESS.getCode(), ReturnMessage.DELETE_SUCCESS.getMessage(), "假删除成功");
    }

    /**
     * 更新订单状态，顺序更新
     *
     * @param orderId 订单id
     * @return 返回resultBean
     */
    @Override
    @Transactional
    @CacheEvict(value = "order", key = "'order'+#orderId")
    public ResultBean updateOrderStatus(Integer orderId) {
        Order byId = this.getById(orderId);
        String currentStatus = byId.getOrderStatus();
        if (currentStatus.equals(OrderStatus.HAVE_ALREADY.getCode()))
            return Result.resultBean(ReturnMessage.ORDER_DONE.getCode(), ReturnMessage.ORDER_DONE.getMessage(), "订单完成了支付,状态码是" + currentStatus);
        Integer currentStatusCode = Integer.valueOf(currentStatus);
        currentStatusCode++;
        byId.setOrderStatus(String.valueOf(currentStatusCode));
        this.updateById(byId);
        return Result.resultBean(ReturnMessage.UPDATE_SUCCESS.getCode(), ReturnMessage.UPDATE_SUCCESS.getMessage(), "状态码是" + byId.getOrderStatus());
    }

    /**
     * 获取未支付订单
     *
     * @return resultBean
     */
    @Override
    @Transactional
    public ResultBean getNonePayOrders() {
        return this.getOrdersByStatus(OrderStatus.NONE_PAY);
    }

    /**
     * 获取没有发货的订单
     *
     * @return resultBean
     */
    @Override
    @Transactional
    public ResultBean getNoneSendOrders() {
        return this.getOrdersByStatus(OrderStatus.NONE_SEND);
    }

    /**
     * 获取没有发货的订单
     *
     * @return resultBean
     */
    @Override
    @Transactional
    public ResultBean getNoneReceiveOrders() {
        return this.getOrdersByStatus(OrderStatus.NONE_RECEIVE);
    }

    /**
     * 以获取已经完成的订单
     *
     * @return resultBean
     */
    @Override
    @Transactional
    public ResultBean getAlreadyOrders() {
        return this.getOrdersByStatus(OrderStatus.HAVE_ALREADY);
    }

    /**
     * 获取取消的订单
     *
     * @return resultBean
     */
    @Override
    @Transactional
    public ResultBean getCancelOrders() {
        return this.getOrdersByStatus(OrderStatus.HAVE_CANCEL);
    }


    /**
     * 取消订单，设置状态进行取消，取消之后恢复资源
     *
     * @param orderId 订单id
     * @return resultBean
     */
    @Override
    @Transactional
    @CacheEvict(value = "order", key = "'order'+#orderId")
    public ResultBean cancelOrder(Integer orderId) {
        UpdateWrapper<Order> orderUpdateWrapper = new UpdateWrapper<>();
        orderUpdateWrapper.eq("order_id", orderId);
        orderUpdateWrapper.set("order_status", OrderStatus.HAVE_CANCEL.getCode());
        //将订单状态设置已取消
        boolean update = this.update(orderUpdateWrapper);
        if (update) {
            //查到该订单
            Order byId = this.getById(orderId);
            //订单号
            Integer productSkuId = byId.getProductSkuId();
            //根据sku获取
            ProductSku productSku = productSkuService.getById(productSkuId);
            UpdateWrapper<ProductSku> updateWrapper = new UpdateWrapper<ProductSku>().eq("product_sku_id", productSku.getProductSkuId()).set("product_sku_stock", productSku.getProductSkuStock() + byId.getOrderNumber()).set("version", productSku.getVersion() + 1);
            boolean cancel = productSkuService.update(updateWrapper);
            if (cancel)
                return Result.resultBean(ReturnMessage.UPDATE_SUCCESS.getCode(), ReturnMessage.UPDATE_SUCCESS.getMessage(), "取消成功");
            return Result.resultBean(ReturnMessage.UPDATE_FAIL.getCode(), ReturnMessage.UPDATE_FAIL.getMessage(), "取消失败");
        }
        return Result.resultBean(ReturnMessage.UPDATE_FAIL.getCode(), ReturnMessage.UPDATE_FAIL.getMessage(), "取消失败");
    }


    /**
     * 用户根据订单状态获取订单
     *
     * @param username    用户的用户名(手机)
     * @param orderStatus 订单状态枚举
     * @return resultBean
     */
    @Override
    @Transactional
    public ResultBean getOrdersByStatus(String username, OrderStatus orderStatus) {
        List<Order> list = this.list(new QueryWrapper<Order>().eq("username", username).eq("order_status", orderStatus.getCode()));
        return handler(list);
    }

    /**
     * 根据订单状态获取所有订单
     *
     * @param orderStatus 订单状态
     * @return resultBean
     */
    @Override
    @Transactional
    public ResultBean getOrdersByStatus(OrderStatus orderStatus) {
        List<Order> list = this.list(new QueryWrapper<Order>().eq("order_status", orderStatus.getCode()));
        return handler(list);
    }

    public String getOrderStatusByProductId(Integer orderId) {
        QueryWrapper<Order> select = new QueryWrapper<Order>().eq("order_id", orderId).select("order_status");
        Order one = this.getOne(select);
        return one.getOrderStatus();
    }

    public void sendDelayMessage(Integer orderId, Integer delayTime) {
        String message = String.valueOf(orderId);
        log.info("当前时间：{}，发送一条时长是{}的信息{}给ttl队列QC", new Date().toString(), delayTime, message);
        rabbitTemplate.convertAndSend(DelayQueueConfig.DELAYED_EXCHANGE_NAME, DelayQueueConfig.DELAYED_ROUTING_KEY, message, msg -> {
            msg.getMessageProperties().setDelay(delayTime);
            return msg;
        });
    }

    /**
     * 支付倒计时，倒计时结束进行查询相关字段
     *
     * @param message
     */
    @Transactional
    @RabbitListener(queues = DelayQueueConfig.DELAYED_QUEUE_NAME)
    public void receiveDelayedMessage(Message message) {
        String msg = new String(message.getBody(), StandardCharsets.UTF_8);
        Integer orderId = Integer.valueOf(msg);
        log.info("当前时间{}收到死信队列的消息{}", new Date().toString(), msg);
        String currentStatus = this.getOrderStatusByProductId(orderId);
        log.info("当前的订单状态是{}", currentStatus);
        log.info("时间到");
        log.info("时间到");
        log.info("时间到");
        log.info("时间到");
        log.info("时间到");
        log.info("时间到");
        log.info("时间到");
        if (currentStatus.equals(OrderStatus.HAVE_ALREADY.getCode())) {

        } else if (currentStatus.equals(OrderStatus.NONE_PAY.getCode())) {
            this.cancelOrder(orderId);
        }
    }

    public ResultBean handler(List<Order> list) {
        List<OrderVo> res = new ArrayList<>();
        for (Order order : list) {
            ProductSku byId = productSkuService.getById(order.getProductSkuId());
            res.add(new OrderVo(order, byId, productService.getById(byId.getProductId())));
        }
        log.info("res是{}", res);
        return ReturnUtils.getList(res);
    }

    @Override
    public ResultBean changePayStatus(Integer orderId) {
        UpdateWrapper<Order> eq = new UpdateWrapper<Order>()
                .set("order_status", "1")
                .eq("order_id", orderId);
        boolean update = update(eq);
        if (update) {
            return ReturnUtils.update(true);
        } else {
            return ReturnUtils.update(false);
        }
    }


}




